﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using EnterpriseDataAccess.DataProviders;

namespace EnterpriseDataAccess
{
    /// <summary>
    /// Clase maestra para conexiones con diferentes origenes de datos.
    /// </summary>
    public interface IDBMaster
    {
        /// <summary>
        /// Obtiene o establece el tipo servidor de base de datos con que se va operar.
        /// </summary>
        Server Server { get; set; }

        /// <summary>
        /// Obtiene o establece la cadena utilizada para abrir una base de datos.
        /// </summary>
        string ConnectionString { get; set; }

        /// <summary>
        /// Lee una secuencia sólo hacia delante de filas de un origen de datos.
        /// </summary>
        DbDataReader DataReader { get; set; }

        /// <summary>
        /// Ejecuta System.Data.Common.DbCommand.CommandText en System.Data.Common.DbCommand.Connection y devuelve un objeto System.Data.Common.DbDataReader.
        /// </summary>
        /// <param name="commandType">Especifica cómo se interpreta una cadena de comando.</param>
        /// <param name="commandText">Establece el comando de texto que se debe ejecutar en el origen de datos.</param>
        /// <param name="parameters">Establece los parametros que se va usar en la consulta.</param>
        /// <param name="useTransaction">Indica si la conexion con la base de datos debe usar una transacción</param>
        /// <returns>Un objeto System.Data.Common.DbDataReader.</returns>
        DbDataReader ExecuteReader(CommandType commandType, string commandText, Dictionary<string,object> parameters = null, bool useTransaction = false);

        /// <summary>
        /// Ejecuta System.Data.Common.DbCommand.CommandText en System.Data.Common.DbCommand.Connection y devuelve un objeto System.Data.DataSet.
        /// </summary>
        /// <param name="commandType">Especifica cómo se interpreta una cadena de comando.</param>
        /// <param name="commandText">Establece el comando de texto que se debe ejecutar en el origen de datos.</param>
        /// <param name="parameters">Establece los parametros que se va usar en la consulta.</param>
        /// <param name="useTransaction">Indica si la conexion con la base de datos debe usar una transacción</param>
        /// <returns>Un objeto System.Data.DataSet.</returns>
        DataSet ExecuteDataSet(CommandType commandType, string commandText, Dictionary<string, object> parameters = null, bool useTransaction = false);

        /// <summary>
        /// Ejecuta System.Data.Common.DbCommand.CommandText en System.Data.Common.DbCommand.Connection y devuelve un objeto System.Data.DataTable.
        /// </summary>
        /// <param name="commandType">Especifica cómo se interpreta una cadena de comando.</param>
        /// <param name="commandText">Establece el comando de texto que se debe ejecutar en el origen de datos.</param>
        /// <param name="parameters">Establece los parametros que se va usar en la consulta.</param>
        /// <param name="useTransaction">Indica si la conexion con la base de datos debe usar una transacción</param>
        /// <returns>Un objeto System.Data.DataTable.</returns>
        DataTable ExecuteDataTable(CommandType commandType, string commandText, Dictionary<string, object> parameters = null, bool useTransaction = false);

        /// <summary>
        /// Ejecuta la consulta y devuelve la primera columna de la primera fila del conjunto de resultados devuelto por la consulta. 
        /// Las demás columnas o filas no se tienen en cuenta.
        /// </summary>
        /// <param name="commandType">Especifica cómo se interpreta una cadena de comando.</param>
        /// <param name="commandText">Establece el comando de texto que se debe ejecutar en el origen de datos.</param>
        /// <param name="parameters">Establece los parametros que se va usar en la consulta.</param>
        /// <param name="useTransaction">Indica si la conexion con la base de datos debe usar una transacción</param>
        /// <returns>Primera columna de la primera fila del conjunto de resultados.</returns>
        object ExecuteScalar(CommandType commandType, string commandText, Dictionary<string, object> parameters = null, bool useTransaction = false);

        /// <summary>
        /// Ejecuta una instrucción SQL en un objeto de conexión.
        /// </summary>
        /// <param name="commandType">Especifica cómo se interpreta una cadena de comando.</param>
        /// <param name="commandText">Establece el comando de texto que se debe ejecutar en el origen de datos.</param>
        /// <param name="parameters">Establece los parametros que se va usar en la consulta.</param>
        /// <param name="useTransaction">Indica si la conexion con la base de datos debe usar una transacción.</param>
        /// <returns>Número de filas afectadas.</returns>
        int ExecuteNonQuery(CommandType commandType, string commandText, Dictionary<string, object> parameters = null, bool useTransaction = false);

        /// <summary>
        /// Libera todos los recursos utilizados.
        /// </summary>
        void Dispose();

        /// <summary>
        /// Procesa todas las filas de un DataTable, y ejecuta una consulta SQL según su estado.
        /// </summary>
        /// <param name="table">DataTable que desea enviar a la Base de Datos.</param>
        /// <param name="useTransaction">Indica si la conexion con la base de datos debe usar una transacción.</param>
        void ProcessDataTable(DataTable table, bool useTransaction = false);

        /// <summary>
        /// Genera automaticamente una consulta SQL, para llenar el System.Data.DataTable especificado, también puede generar la
        /// clausula WHERE en base las llaves primarias detectadas.
        /// </summary>
        /// <param name="table">DataTable que desea llenar.</param>
        /// <param name="parameters">Establece los parametros que se va usar en la consulta.</param>
        /// <param name="useTransaction">Indica si la conexion con la base de datos debe usar una transacción.</param>
        void FillDataTable(DataTable table, Dictionary<string, object> parameters = null, bool useTransaction = false);
    }
}
